package cse481.economy;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

/**
 * Handles the network traffic and calls the necessary
 * @author monster
 */
public class GamesServlet extends HttpServlet {
	public void doGet(HttpServletRequest request,
			HttpServletResponse response)
	throws ServletException, IOException {
		doPost(request, response);
	}
	
	public void doPost(HttpServletRequest request,
			HttpServletResponse response)
	throws ServletException, IOException {
		JSONObject data = JSONObject.fromObject(request.getParameter("data"));
		response.setContentType("text/plain");
		PrintWriter out = new PrintWriter(response.getOutputStream());
		DBHandler db = new DBHandler(); 	// Should this prepare all statements?
		JSONObject ret = null;
		int action = data.getInt("action");
		switch (action) {
		case GamesConstant.ADD_PLAYER: 
			ret = addPlayer(db,data,out);
			break;
		case GamesConstant.ADD_CREW:
			ret = addCrew(db,data,out);
			break;
		case GamesConstant.ADD_SHIP:
			ret = addShip(db,data,out);
			break;
		case GamesConstant.ADD_INVENTORY:
			ret = addItem(db,data,out);
			break;
		case GamesConstant.BUILD_STRUCTURE:
			ret = constructBuilding(db,data,out);
			break;
		case GamesConstant.CHANGE_ACTIVE_SHIP:
			ret = changeActiveShip(db,data,out);
			break;
		case GamesConstant.COMPLETE_QUEST:
			ret = completeQuest(db,data,out);
			break;
		case GamesConstant.EQUIP_ITEM_TO_SHIP:
			ret = equipToShip(db,data,out);
			break;
		case GamesConstant.GET_CREW_INFO:
			ret = getCrewInfo(db,data,out);
			break;
		case GamesConstant.GET_PLAYER_INFO:
			ret = getPlayerInfo(db,data,out);
			break;
		case GamesConstant.GET_SALES_LISTING:
			ret = getSalesListing(db,data,out);
			break;
		case GamesConstant.UPDATE_PLAYER_XP:
			ret = updatePlayerXP(db,data,out);
			break;
		case GamesConstant.GET_INVENTORY:
			ret = getInventory(db,data,out);
			break;
		case GamesConstant.GET_SHIPS:
			ret = getShips(db,data,out);
			break;
		case GamesConstant.GET_SHIP_EQUIPMENT:
			ret = getShipEquipment(db,data,out);
			break;
		case GamesConstant.GET_BUILDINGS:
			ret = getBuildings(db, data, out);
			break;
		case GamesConstant.GET_PLAYER_ITEMS_FOR_SALE:
			ret = getPlayerItemsForSale(db,data,out);
			break;
		case GamesConstant.GET_PLAYER_ITEMS_FOR_SALE_AT:
			ret = getPlayerItemsForSaleAt(db,data,out);
			break;
		case GamesConstant.GET_CREW_AT:
			ret = getCrewAt(db,data,out);
			break;
		case GamesConstant.CHANGE_PLAYER_LOCATION:
			ret = changePlayerLocation(db,data,out);
			break;
		case GamesConstant.ASSIGN_NEW_QUEST:
			ret = assignNewQuest(db,data,out);
			break;
		case GamesConstant.UPDATE_QUEST_MIN_LEFT:
			ret = updateQuestMinLeft(db,data,out);
			break;
		case GamesConstant.MOVE_ITEM:
			ret = moveItem(db,data,out);
			break;
		case GamesConstant.UPDATE_SALES_LISTING:
			ret = updateSalesListing(db,data,out);
			break;
		case GamesConstant.BUY_ITEM:
			ret = buyItem(db,data,out);
			break;
		case GamesConstant.UPDATE_GOLD:
			ret = updateGold(db,data,out);
			break;
		case GamesConstant.DELETE_SHIP:
			ret = deleteShip(db,data,out);
			break;
		case GamesConstant.DELETE_BUILDING:
			ret = deleteStructure(db,data,out);
			break;
		case GamesConstant.GET_QUESTS:
			ret = getQuests(db,data,out);
			break;
		case GamesConstant.REMOVE_FROM_INVENTORY:
			ret = dropItem(db,data,out);
			break;
		case GamesConstant.UPDATE_CREW:
			ret = updateCrew(db,data,out);
			break;
		case GamesConstant.UPDATE_TUTORIAL_PROGRESS:
			ret = updateTutorialProgress(db,data,out);
			break;
		case GamesConstant.UPDATE_QUEST_CONTRIBUTION:
			ret = updateQuestContribution(db,data,out);
			break;
		case GamesConstant.UPDATE_QTY:
			ret = updateQty(db,data,out);
			break;
		case GamesConstant.SALE_NOTIFY_COMPLETED:
			ret = saleNotifyCompleted(db,data,out);
			break;
		}
		
		ret.write(out);
		response.setStatus(200);
		out.close();
	}
	
	private JSONObject updateCrew(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.moveCrew(
				data.getInt("pid"),
				data.getInt("oldlid"),
				data.getInt("oldtid"),
				data.getInt("newlid"),
				data.getInt("newtid"),
				data.getInt("qty"));
		ret.put("action", GamesConstant.UPDATE_CREW);
		
		return ret;
				
	}
	
	private JSONObject addCrew(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.addCrewToShip(
				data.getInt("pid"),
				data.getInt("lid"),
				data.getInt("tid"));
		ret.put("action", GamesConstant.ADD_CREW);
		
		return ret;
	}
	
	private JSONObject updateGold(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.updateGold(
				data.getInt("pid"),
				data.getInt("amt"));
		ret.put("action", GamesConstant.UPDATE_GOLD);
		
		return ret;
	}
	
	private JSONObject buyItem(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		if (!data.has("sellerPid") || !data.has("buyerPid")) {
			return new JSONObject();
		}
		
		JSONObject ret = db.buy(
				data.getInt("buyerPid"),
				data.getInt("sellerPid"),
				data.getInt("invItemId"),
				data.getInt("itemId"), 
				data.getInt("salePrice"),
				data.getInt("qty"), 
				data.getInt("sellToLocId"));
		ret.put("action", GamesConstant.BUY_ITEM);
		
		return ret;
	}
	
	private JSONObject saleNotifyCompleted(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.saleNotifyCompleted(
				data.getInt("invItemId"),
				data.getInt("soldQtySinceNotify"));
		ret.put("action", GamesConstant.SALE_NOTIFY_COMPLETED);
		
		return ret;
	}
	
	private JSONObject updateSalesListing(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.updateItemSale(
				data.getInt("invId"), 
				data.getInt("quantity"),
				data.getInt("price"));
		ret.put("action", GamesConstant.UPDATE_SALES_LISTING);
		
		return ret;
	}
	
	private JSONObject moveItem(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.moveItem(
				data.getInt("invItemId"), 
				data.getInt("lid"),
				data.getInt("quantity"));
		ret.put("action", GamesConstant.MOVE_ITEM);
		
		return ret;
	}
	
	private JSONObject addItem(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.addItem(
				data.getInt("pid"), 
				data.getInt("itemId"),
				data.getInt("lid"),
				data.getInt("quantity"));
		ret.put("action", GamesConstant.ADD_INVENTORY);
		
		return ret;
	}
	
	private JSONObject assignNewQuest(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.assignQuest(
				data.getInt("pid"), 
				data.getInt("minLeft"), 
				data.getInt("templateId"), 
				data.getInt("fromId"), 
				data.getInt("lid"), 
				data.getInt("reqItemId"), 
				data.getInt("reqItemQty"), 
				data.getInt("rewItemId"), 
				data.getInt("rewItemQty"));
		ret.put("action", GamesConstant.ASSIGN_NEW_QUEST);
		
		return ret;		
	}
	
	private JSONObject updateQuestMinLeft(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.updateQuestMinLeft(
				data.getInt("id"), 
				data.getInt("newMinLeft"));
		ret.put("action", GamesConstant.UPDATE_QUEST_MIN_LEFT);
		
		return ret;
	}
	
	private JSONObject changePlayerLocation(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.changePlayerLoc(
				data.getInt("pid"),
				data.getInt("lid"));
		ret.put("action", GamesConstant.CHANGE_PLAYER_LOCATION);
		
		return ret;
	}
	
	private JSONObject getCrewAt(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.getCrewAt(
				data.getInt("pid"), 
				data.getInt("lid"));
		ret.put("action", GamesConstant.GET_CREW_AT);
		
		return ret;
	}
	
	private JSONObject getPlayerItemsForSaleAt(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.getPlayerItemsForSaleAt(
				data.getInt("pid"),
				data.getInt("lid"));
		ret.put("action", GamesConstant.GET_PLAYER_ITEMS_FOR_SALE_AT);
		
		return ret;
	}
	
	private JSONObject getInventory(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.getInventoryAt(
				data.getInt("pid"),
				data.getInt("lid"));
		ret.put("action", GamesConstant.GET_INVENTORY);
		
		return ret;
	}
	
	private JSONObject getShips(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.getShips(data.getInt("pid"));
		ret.put("action", GamesConstant.GET_SHIPS);
		
		return ret;
	}

	private JSONObject getShipEquipment(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.getShipEquipment(data.getInt("shipId"));
		ret.put("action", GamesConstant.GET_SHIP_EQUIPMENT);
		
		return ret;
	}
	
	private JSONObject getBuildings(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.getBuildings(
				data.getInt("pid"),
				data.getInt("lid"));
		ret.put("action", GamesConstant.GET_BUILDINGS);
		
		return ret;
	}
	
	private JSONObject getPlayerItemsForSale(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.getPlayerItemsForSale(data.getInt("pid"));
		ret.put("action", GamesConstant.GET_PLAYER_ITEMS_FOR_SALE);
		
		return ret;
	}
	
	private JSONObject updatePlayerXP(
			DBHandler db, 
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.updatePlayerXp(
				data.getInt("id"), 
				data.getInt("experience"));
		ret.put("action", GamesConstant.UPDATE_PLAYER_XP);
		
		return ret;
	}

	private JSONObject getSalesListing(DBHandler db, JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.getItemsForSaleAt(data.getInt("locationId"));
		ret.put("action", GamesConstant.GET_SALES_LISTING);
		
		return ret;
	}
	
	private JSONObject getQuests(DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.getQuests(data.getInt("pid"));
		ret.put("action", GamesConstant.GET_QUESTS);
		
		return ret;
	}

	
	private JSONObject getPlayerInfo(DBHandler db, 
			JSONObject data,
			PrintWriter out) {
		String email = data.getString("email");
		JSONObject ret = db.getPlayer(email);
		ret.put("action", GamesConstant.GET_PLAYER_INFO);
		
		return ret;
	}

	private JSONObject getCrewInfo(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.getCrew(data.getInt("pid"));
		ret.put("action", GamesConstant.GET_CREW_INFO);
		
		return ret;
	}

	private JSONObject equipToShip(DBHandler db, JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.equipToShip(
				data.getInt("shipId"), 
				data.getInt("slotId"), 
				data.getInt("itemId"), 
				data.getInt("capacity"), 
				data.getInt("defense"), 
				data.getInt("newConsRes1"), 
				data.getInt("newConsQty1"), 
				data.getInt("newConsRes2"), 
				data.getInt("newConsQty2"));
		ret.put("action", GamesConstant.EQUIP_ITEM_TO_SHIP);
		return ret;
	}

	private JSONObject completeQuest(DBHandler db, JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.endQuest(
				data.getInt("qid"),
				(data.getInt("completed") == 1),
				data.getInt("pid"),
				data.getInt("reqItemId"),
				data.getInt("reqItemQty"),
				data.getInt("rewlid"),
				data.getInt("rewItemId"),
				data.getInt("rewQty"));
		ret.put("action", GamesConstant.COMPLETE_QUEST);
		
		return ret;
	}

	private JSONObject changeActiveShip(DBHandler db, JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.changeActiveShip(
				data.getInt("pid"), 
				data.getInt("sid"));
		ret.put("action", GamesConstant.CHANGE_ACTIVE_SHIP);
		
		return ret;
	}

	private JSONObject constructBuilding(DBHandler db, JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.constructBuilding(
				data.getInt("pid"),
				data.getInt("locationId"),
				data.getInt("buildingId"));
		ret.put("action", GamesConstant.BUILD_STRUCTURE);
		
		return ret;
	}
	
	private JSONObject deleteStructure(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.deleteBuilding(data.getInt("bldgId"));
		ret.put("action", GamesConstant.DELETE_BUILDING);
		
		return ret;
	}

	private JSONObject deleteShip(
			DBHandler db,
			JSONObject data,
			PrintWriter out) {
		JSONObject ret = db.deleteShip(data.getInt("shipId"));
		ret.put("action", GamesConstant.DELETE_SHIP);
		
		return ret;		
	}
	
	private JSONObject addShip(
			DBHandler db, 
			JSONObject data, 
			PrintWriter out) {
		JSONObject ret = db.addShip(
				data.getInt("pid"),
				data.getInt("shipTypeId"),
				data.getInt("speed"),
				data.getInt("defense"),
				data.getInt("navigation"),
				data.getInt("slots"),
				data.getInt("capacity"),
				data.getInt("maintenance"),
				data.getInt("fuelEfficiency"),
				data.getInt("consRes1"),
				data.getInt("consQty1"),
				data.getInt("consRes2"),
				data.getInt("consQty2")
				);
		ret.put("action", GamesConstant.ADD_SHIP);
		
		return ret;
	}

	private JSONObject addPlayer(DBHandler db, JSONObject data, PrintWriter out) {
		if (!data.has("name")) {
			return new JSONObject();
		}
		
		JSONObject ret = db.addPlayer(
				data.getString("email"),
				data.getString("name"),
				data.getInt("lid"));
		ret.put("action", GamesConstant.ADD_PLAYER);
		
		return ret;
	}
	
	private JSONObject dropItem(DBHandler db, JSONObject data, PrintWriter out) {
		JSONObject ret = db.dropItem(
				data.getInt("invItemId"));
		ret.put("action", GamesConstant.REMOVE_FROM_INVENTORY);
		
		return ret;
	}
	
	private JSONObject updateTutorialProgress(DBHandler db, JSONObject data, PrintWriter out) {
		JSONObject ret = db.updateTutorialProgress(
				data.getInt("pid"),
				data.getInt("tutPro"));
		ret.put("action", GamesConstant.UPDATE_TUTORIAL_PROGRESS);
		
		return ret;
	}
	
	private JSONObject updateQuestContribution(DBHandler db, JSONObject data, PrintWriter out) {
		JSONObject ret = db.updateQuestContribution(
				data.getInt("id"),
				data.getInt("newContribution"));
		ret.put("action", GamesConstant.UPDATE_QUEST_CONTRIBUTION);
		
		return ret;
	}
	
	private JSONObject updateQty(DBHandler db, JSONObject data, PrintWriter out) {
		JSONObject ret = db.updateQty(
				data.getInt("invItemId"),
				data.getInt("qty"));
		ret.put("action", GamesConstant.UPDATE_QTY);
		
		return ret;
	}
}
